package com.movie.ticket.sale.moviezuul.filter;


import com.fasterxml.jackson.databind.ObjectMapper;
import com.movie.ticket.sale.moviecommon.common.Result;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StreamUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 颁发token
 */
@Component
@Slf4j
@RefreshScope
public class GrantFilter extends ZuulFilter {

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private JWTHelper jwtHelper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Value("${myUrls.myNoContent}")   //乱码不设置的url
    private String myNoContent;

    @Override
    public String filterType() {
        return FilterConstants.POST_TYPE;
    }

    @Override
    public int filterOrder() {
        return FilterConstants.RIBBON_ROUTING_FILTER_ORDER + 10;
    }

    /**
     * 判断请求是否是登录请求,只拦截登录
     *
     * @return
     */
    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        int responseStatusCode = ctx.getResponseStatusCode();
        //获取url
        String requestURI = request.getRequestURI();

        //解决乱码：
        String ars[] = myNoContent.split(",");
        boolean bo = true;
        for (String s : ars)    //不设置字符集的路径
            if (s.equals(requestURI)&&responseStatusCode==200)
                bo = false;
        if (bo)
            ctx.getResponse().setContentType("application/json;charset=utf-8");

        log.info("------ 颁发token，request.uri： {}", requestURI);
        log.info("------ 响应码：{}",responseStatusCode);
        //如果请求的地址时 登录 的话  执行
        return ("/author/login/namePass".equals(requestURI) || "/author/login/checkTelCode".equals(requestURI)) && responseStatusCode == 200;
    }

    @Override
    public Object run() throws ZuulException {
//        log.info("进入：颁发token");

        try {
            //获取当前请求上下文
            RequestContext ctx = RequestContext.getCurrentContext();
            //获取响应 响应回来的信息 保存在 response中
            HttpServletResponse response = ctx.getResponse();

            //Result -> String -> OutPutStream
            //读取Result对象 InputStream -> String -> Result
            InputStream responseDataStream = ctx.getResponseDataStream();
            String token = null;

            String resultStr = StreamUtils.copyToString(responseDataStream, StandardCharsets.UTF_8);
            //请求的请求头中
            Result result = objectMapper.readValue(resultStr, Result.class);
            log.info("登录请求结果：{}", result);
            //登录成功
            if (result.isSuccess()) {
                //登录成功过后返回了用户相关的数据
                Object userInfo = result.getData();
                Map<String, Object> map = (Map<String, Object>) userInfo;

                Date expireDate = DateUtils.addDays(new Date(), 3);//过期时间
                //颁发token
                token = jwtHelper.createJWT(expireDate, map);
                log.info("颁发token：{}", token);

                String key = "manager." + map.get("role") + "." + map.get("id");
                BoundValueOperations<String, String> rs = redisTemplate.boundValueOps(key);
                String value = map.get("tel") + "-:-" + token + "-:-" + new Date().getTime();
                rs.set(value, 3, TimeUnit.DAYS);

                response.setHeader("token", "pass" + token);
            }
            //将结果重新写入response
            response.setContentType("application/json;charset=utf-8");
            ctx.setSendZuulResponse(true);
            ctx.setResponseBody(resultStr);
            return "pass" + token;

        } catch (Exception e) {
//            ReflectionUtils.rethrowRuntimeException(e);
            e.printStackTrace();
            log.info("颁发token异常：{}", e.getMessage());
            return Result.fail(426, e.getMessage());
        }

    }
}
